//
// Created by fairy on 2025/7/28.
//

#ifndef FT4X46_HPP
#define FT4X46_HPP


#include <gpio.hpp>
#include <i2c.hpp>
#include <hal_delay.hpp>

#include "touch.hpp"


// 理应与ft6336合并在一块的，有空再合并
namespace bsp::touch::detail_ft4x46
{
    // ========================== 设备状态码 ==========================
    static constexpr uint8_t OK = true; ///< 操作成功标志
    static constexpr uint8_t ERROR = false; ///< 操作失败标志

    // ======================== 设备逻辑状态定义 ========================
    static constexpr uint8_t FALSE = 0; ///< 逻辑假值（基础状态）
    static constexpr uint8_t TRUE = 1; ///< 逻辑真值（基础状态）
    static constexpr uint8_t FALSE1 = 2; ///< 扩展假值1（特殊错误状态）
    static constexpr uint8_t FALSE2 = 3; ///< 扩展假值2（特殊错误状态）


    static constexpr uint8_t NUM_FINGER = 0x02; ///< 触摸点数量寄存器（0-2个触点）
    // ======================== 设备物理层参数 =========================
    static constexpr uint8_t ADDR = 0x71; ///< I2C设备地址（读地址格式，右移一位即7位地址格式）
    static constexpr uint16_t HOR = 1024;
    static constexpr uint16_t VER = 600;

    // ======================== 寄存器地址定义 =========================
    enum class Reg {
        // --------------------- 基础功能寄存器 --------------------------
        MODE = 0x00, ///< 模式控制寄存器（默认值：0x00）
        NUM_FINGER = 0x02, ///< 触摸点数量寄存器（0-2个触点）
        // --------------------- 触摸数据寄存器 ----------------------------
        TP1 = 0x03, ///< 第1触摸点数据首地址（包含X/Y坐标等数据）
        TP2 = 0x09, ///< 第2触摸点数据首地址（包含X/Y坐标等数据）
        // --------------------- 设备配置寄存器 ---------------------
        ID_G_FOCALTECH_ID = 0xA8, ///< 厂商ID寄存器（默认值：0x11，只读）
    };

    // ======================== 参数定义 =========================
    enum class Params {
        // --------------------- 面板参数 ---------------------
        PANNEL_ID = 0x11, ///< 面板标识码（用于多面板系统识别，默认0x11）
    };

    /**GPIO引脚定义
    PB5     ------> CTP_RST
    PB6     ------> CTP_INT
    */
    using TOUCH_RST = hal::gpio::pinOld<GPIOB_BASE,GPIO_PIN_5>; // 触摸屏复位引脚
    using i2c = hal::i2c1;
}


namespace bsp::touch
{
    class FT4x46 {
    public:
        static uint8_t init()
        {
            using namespace hal;
            using namespace hal::gpio;

            // 初始化i2c1
            detail_ft4x46::i2c::init();

            //配置GPIO
            detail_ft4x46::TOUCH_RST::init<mode::output_pp, pull::up>();

            // 重置
            detail_ft4x46::TOUCH_RST::clear();
            delay::us(10);
            detail_ft4x46::TOUCH_RST::set();
            delay::ms(50);

            std::array<uint8_t, 1> id_reg{100};

            if (const HAL_StatusTypeDef status = i2c1::readMemory(detail_ft4x46::ADDR,
                                                                  static_cast<uint16_t>(detail_ft4x46::Reg::ID_G_FOCALTECH_ID),
                                                                  id_reg); !status) {
                return detail_ft4x46::FALSE1; //I2C通信故障
            }
            if (id_reg[0] != static_cast<uint16_t>(detail_ft4x46::Params::PANNEL_ID)) {
                return detail_ft4x46::FALSE2; //寄存器值不匹配
            }
            return id_reg[0];
        }

        static bool get_single_point(int16_t &x, int16_t &y)
        {
            using namespace hal;
            std::array<uint8_t, 1> point_number{};
            std::array<uint8_t, 4> touch_pos{};

            // 读取触摸点的数量
            i2c1::readMemory(detail_ft4x46::ADDR, static_cast<uint16_t>(detail_ft4x46::Reg::NUM_FINGER), point_number); //读点数

            // 如果没有触摸点，返回0
            if (point_number[0] == 0) {
                return false;
            }

            // 读取第一个触摸点的坐标
            i2c1::readMemory(detail_ft4x46::ADDR, static_cast<uint16_t>(detail_ft4x46::Reg::TP1), touch_pos); //读坐标

            // 解析触摸点的坐标 横屏
            x = (static_cast<int16_t>((touch_pos[2] & 0x0F) << 8)) | touch_pos[3];
            y = (static_cast<int16_t>((touch_pos[0] & 0x0F) << 8)) | touch_pos[1];

            // 返回1表示有触摸点
            return true;
        }
    };
}

#endif //FT4X46_HPP
